package org.example.services.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;

@Aspect   //是aspectj框架的注解，表示当前类是切面类
public class MyAspect {

    /**
     * @Before:前置通知
     * 属性value切入点表达式 表示切面执行的位置
     * 位置：方法的定义上面
     */
    //@Before(value = "execution(* org.example.services.aop.SomeServiceImpl.doSome(..))")
    public void myBefore() {
        //就是切面代码的功能，例如日志的输出，事务的处理
        System.out.println("前置通知：在目标方法之前先执行，例如输出日志");
    }


    @Before(value = "execution(* org.example.services.aop.SomeServiceImpl.do*(..))")
    public void aaBefore(JoinPoint jp) {
        //JoinPoint能够获取到方法的定义，方法的参数等信息
        System.out.println("连接点的方法定义："+jp.getSignature());
        System.out.println("连接点方法的参数个数："+jp.getArgs().length);



        //方法参数的信息
        Object args[] = jp.getArgs();
        for (Object arg : args) {
            System.out.println(arg);
        }

        //就是切面代码的功能，例如日志的输出，事务的处理
        System.out.println("前置通知：在目标方法之前先执行，例如输出日志");
    }


    @AfterReturning(value = "execution(* org.example.services.aop.SomeServiceImpl.doOther(..))",returning = "result")
    public void myAfterReturning(Object result) {
        //修改目标方法的执行结果
        if (result != null) {
            String s = (String) result;
            result = s.toUpperCase();
        }

        System.out.println("后置通知：在目标方法之后执行的功能增强，例如执行事务处理切面"+result);
    }


    @Around(value = "execution(* org.example.services.aop.SomeServiceImpl.doFirst(..))")
    public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
        Object obj = null;
        //增强功能
        System.out.println("环绕通知：在目标方法之前执行的，例如输出日志");
        //执行目标方法的调用，等同于method.invoke(target,args)
        obj = pjp.proceed();

        //增强功能
        System.out.println("环绕通知：在目标方法之后执行的，例如处理事务");

        //返回目标方法的执行结果
        return obj;
    }


    @AfterThrowing(value = "execution(* org.example.services.aop.SomeServiceImpl.doSecond(..))",throwing = "ex")
    public void myAfterThrowing(Throwable ex) {
        //把异常发生的时间，位置，原因记录到数据库，日志文件等等
        //可以在异常发生时，把异常信息通过短信，邮件发送给开发人员
        System.out.println("异常通知：在目标方法抛出异常时执行的，异常原因："+ex.getMessage());
    }



    @After(value = "execution(* org.example.services.aop.SomeServiceImpl.doThird(..))")
    public void myAfter() {
        System.out.println("最终通知：总是会被执行的方法");
    }
}
